using System;
using System.Data;
using System.IO;

namespace FreeFlow.Administration
{
	/// <summary>
	/// A version of a library in the database.
	/// </summary>
  public class Version : DatabaseAware, IDeletable, IUpdatable
  {
    internal Version(Server server, IDataReader reader) : base(server)
    {
      name = reader["eProcedureName"].ToString();
      type = reader["eProcedureType"].ToString();
      versionNumber = Convert.ToInt32(reader["eVersion"]);
      owner = reader["eProcessOwner"].ToString();
      if (reader["eworkVersion"] is System.DBNull)
        eworkVersion = 5;
      else
        eworkVersion = Convert.ToInt32(reader["eworkVersion"]);
      publishedTime = (DateTime)reader["eLoadedTime"];
      description = reader["eNotes"].ToString();

      // defer reading size until later
    }

    /// <summary>
    /// Saves this version of the procedure or library to the specified file.
    /// </summary>
    /// <param name="fileName">Name of the file to save to.</param>
    public void SaveToFile(string fileName)
    {
      using (FileStream stream = new FileStream(fileName, FileMode.Create))
      {
        SaveToStream(stream);
      }
    }

    /// <summary>
    /// Saves this version of the procedure or library to the specified stream.
    /// </summary>
    /// <param name="stream">The stream to write the procedure or library to.</param>
    public void SaveToStream(Stream stream)
    {
      using (IDataReader reader = Server.ExecuteReader(
        string.Format("SELECT eProcedure FROM eProcedure WHERE eProcedureName = '{0}' AND eVersion = {1}", name, versionNumber)))
      {
        reader.Read();
        size = reader.GetBytes(0, 0, null, 0, 0);  //get the length of data
        byte[] values = new byte[size];

        int bufferSize = 16000;
        long bytesRead = 0;
        int curPos = 0;

        while (bytesRead < size)
        {
          bytesRead += reader.GetBytes(0, curPos, values, curPos, bufferSize);
          curPos += bufferSize;
        }

        stream.Write(values, 0, values.Length);
      }
    }

    private string name;
    /// <summary>
    /// Gets the name of the procedure or library.
    /// </summary>
    public string Name
    {
      get
      {
        return name;
      }
    }

    private string type;
    /// <summary>
    /// Gets the type of file stored in the database.
    /// </summary>
    public string Type
    {
      get
      {
        return type;
      }
    }

    /// <summary>
    /// Gets the file name of the procedure or library.
    /// </summary>
    public string FileName
    {
      get
      {
        return name + "." + type;
      }
    }

    private int versionNumber;
    /// <summary>
    /// Gets the version number.
    /// </summary>
    public int VersionNumber
    {
      get
      {
        return versionNumber;
      }
    }

    private string owner;
    /// <summary>
    /// Gets the owner of this version of the procedure or library.
    /// </summary>
    public string Owner
    {
      get
      {
        return owner;
      }
    }

    private int eworkVersion;
    /// <summary>
    /// Gets the version of Metastorm BPM used to publish this version of the procedure or library.
    /// </summary>
    public int EworkVersion
    {
      get
      {
        return eworkVersion;
      }
    }

    private DateTime publishedTime;
    /// <summary>
    /// Gets the time when this version of the procedure or library was published.
    /// </summary>
    public DateTime PublishedTime
    {
      get
      {
        return publishedTime;
      }
    }

    private string description;
    /// <summary>
    /// Gets or sets the description of this version of the procedure or library.
    /// </summary>
    public string Description
    {
      get
      {
        return description;
      }
      set
      {
        description = value;
      }
    }

    private long size;
    /// <summary>
    /// Gets the size in bytes of the file.
    /// </summary>
    public long Size
    {
      get
      {
        if (size == 0)
        {
          using (IDataReader reader = Server.ExecuteReader(
          string.Format("SELECT eProcedure FROM eProcedure WHERE eProcedureName = '{0}' AND eVersion = {1}", name, versionNumber)))
          {
            reader.Read();
            size = reader.GetBytes(0, 0, null, 0, 0);  //get the length of data
          }
        }
        return size;
      }
    }

    #region IDeletable Members

    /// <summary>
    /// Deletes this version of the procedure or library from the database.
    /// </summary>
    public void Delete()
    {
      Server.ExecuteNonQuery(string.Format("DELETE FROM eProcedure WHERE eProcedureName='{0}' AND eVersion='{1}'", name, versionNumber));
    }

    #endregion
    #region IUpdatable Members

    /// <summary>
    /// Applies the changes made to this version.
    /// </summary>
    public void ApplyChanges()
    {
      Server.ExecuteNonQuery(string.Format(
        "UPDATE eProcedure SET eNotes='{0}' WHERE eProcedureName='{1}' AND eVersion={2}",
        SqlEscape(description), SqlEscape(Name), VersionNumber));
    }

    #endregion
  }
}
